package com.example.controller;

import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayConfig;
import com.alipay.api.internal.util.AlipaySignature;
import com.example.config.AliConfig;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * 支付宝异步通知控制器
 * 处理支付宝支付完成后发送的异步通知消息
 */
@RestController
@Slf4j
public class NotifyController {

    // 自动注入支付宝配置类
    @Autowired
    private AliConfig aliConfig;

    /**
     * 支付宝异步通知处理接口
     * 接收支付宝发送的支付结果通知，并进行验签处理
     *
     * @param request HTTP请求对象，包含支付宝发送的通知参数
     * @return success表示处理成功，failure表示处理失败
     * @throws AlipayApiException 支付宝API调用异常
     */
    @RequestMapping("/notify")
    public String notify(HttpServletRequest request) throws AlipayApiException {
        // 将请求参数转换为Map格式
        Map<String, String> params = convertRequestParamsToMap(request);
        // 将参数转换为JSON字符串，用于日志记录
        String paramsJson = JSON.toJSONString(params);
        // 获取支付宝配置信息
        AlipayConfig alipayConfig = aliConfig.getConfig();
        // 使用支付宝公钥对通知参数进行签名验证
        boolean signVerified = AlipaySignature.rsaCertCheckV1(params, alipayConfig.getAlipayPublicCertPath(),
                alipayConfig.getCharset(), alipayConfig.getSignType());
        // 验签成功
        if (signVerified) {
            log.info("支付宝异步通知验签成功");
            log.info("支付宝异步通知: {}", paramsJson);
            // 返回success告知支付宝服务器已成功接收通知
            return "success";
        }
        // 验签失败，返回failure
        return "failure";
    }

    /**
     * 将HTTP请求参数转换为Map格式
     *
     * @param request HTTP请求对象
     * @return 包含所有请求参数的Map
     */
    private static Map<String, String> convertRequestParamsToMap(HttpServletRequest request) {
        // 创建用于存储参数的Map
        Map<String, String> retMap = new HashMap<>();

        // 获取请求参数的键值对集合
        Set<Map.Entry<String, String[]>> entrySet = request.getParameterMap().entrySet();

        // 遍历所有参数
        for (Map.Entry<String, String[]> entry : entrySet) {
            String name = entry.getKey();           // 参数名
            String[] values = entry.getValue();     // 参数值数组
            int valLen = values.length;             // 参数值个数

            // 单个值的情况
            if (valLen == 1) {
                retMap.put(name, values[0]);
            }
            // 多个值的情况，用逗号连接
            else if (valLen > 1) {
                StringBuilder sb = new StringBuilder();
                for (String val : values) {
                    sb.append(",").append(val);
                }
                retMap.put(name, sb.substring(1)); // 去掉开头的逗号
            }
            // 无值的情况
            else {
                retMap.put(name, "");
            }
        }

        return retMap;
    }

}
